﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ThuVien
{
    public class ValidateUtils
    {
        private static string reAlphabetic = "^[a-zA-Z]+$";
        private static string reAlphanumeric = "^[a-zA-Z0-9]+$";
        private static string reChar = "^[a-zA-Z0-9-_ ]+$";
        private static string reNumberLetter = "^\\d+$";
        private static string reUSPhone = "^(\\d{3}|(\\()\\d{3}\\))(\\d{3}|(\\-)?(\\d{3})(\\-)?|(\\ )?(\\d{3})(\\-)?)(\\d{4})$";
        private static string reUSZip = "^(\\d{5})((\\-)?(\\d{4}))?$";
        private static string reSSN = "^(\\d{3})(\\-)?\\d{2}(\\-)?\\d{4}$";
        private static string reUserName = "^[a-zA-Z0-9](\\w+)?$";
        private static string reURL = @"((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)\b";
        public static string reEmail = @"^([a-zA-Z0-9_\-\.\+]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";

        private static string reFileName = @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\""|/]+$";
        private static string reIP = @"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$";

        /// <summary>
        /// ham dung de check du lieu co dung theo mot dinh dang cho truoc khong
        /// </summary>
        /// <param name="s">s can check xem co dung dinh dang khong</param>
        /// <param name="strRegurlarExpression">la chuoi dinh dang (Regurlar Expression)</param>
        /// <returns>true : dung; false : sai</returns>
        public static bool CheckRegurlarExpression(object s, string strRegurlarExpression)
        {
            string tmp = ((FunctionsUtils.IsNullOrEmpty(s) == true) ? string.Empty : s.ToString());
            try
            {
                return Regex.IsMatch(tmp, strRegurlarExpression, RegexOptions.IgnoreCase);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// ham kiem tra mot chuoi co phai la so
        /// </summary>
        /// <param name="o">chuoi can kiem</param>
        /// <param name="numType">cac kieu so nhu la Integer, Long, Double, Decimal, Float</param>
        /// <returns></returns>
        public static bool isNumber(object o, NumberType numberType)
        {
            bool bResult = true;
            try
            {
                if (o == null)
                    bResult = false;
                else
                {
                    string s = o.ToString();
                    switch (numberType)
                    {
                        case NumberType.Integer:
                            int i = int.Parse(s);
                            break;
                        case NumberType.Long:
                            long l = long.Parse(s);
                            break;
                        case NumberType.Double:
                            double d = double.Parse(s);
                            break;
                        case NumberType.Decimal:
                            decimal de = decimal.Parse(s);
                            break;
                        case NumberType.Float:
                            float f = float.Parse(s);
                            break;
                    }
                }
            }
            catch
            {
                bResult = false;
            }
            return bResult;
        }

        /// <summary>
        /// kiem tra so duong lon hon or bang 0
        /// </summary>
        /// <param name="o"></param>
        /// <param name="numberType"></param>
        /// <returns></returns>
        public static bool isPosNumber(object o, NumberType numberType)
        {
            bool bResult = false;
            if (isNumber(o, numberType) == true)
            {
                string s = o.ToString();
                switch (numberType)
                {
                    case NumberType.Integer:
                        if (int.Parse(s) >= 0)
                            bResult = true;
                        break;
                    case NumberType.Long:
                        if (long.Parse(s) >= 0)
                            bResult = true;
                        break;
                    case NumberType.Decimal:
                        if (decimal.Parse(s) >= 0)
                            bResult = true;
                        break;
                    case NumberType.Double:
                        if (double.Parse(s) >= 0)
                            bResult = true;
                        break;
                    case NumberType.Float:
                        if (float.Parse(s) >= 0)
                            bResult = true;
                        break;
                }
            }
            return bResult;
        }

        /// <summary>
        /// kiem tra so duong lon hon hoac bang 0
        /// </summary>
        /// <param name="o"></param>
        /// <param name="numberType"></param>
        /// <param name="EqualZero">true : cho phep bang 0, else lon hon 0</param>
        /// <returns></returns>
        public static bool isPosNumber(object o, NumberType numType, bool EqualZero)
        {
            bool bResult = false;
            if (isNumber(o, numType) == true)
            {
                if (EqualZero == true) //lon hon hoac bang 0
                {
                    bResult = isPosNumber(o, numType);
                }
                else //lon hon 0
                {
                    string s = o.ToString();
                    switch (numType)
                    {
                        case NumberType.Integer:
                            if (int.Parse(s) > 0)
                                bResult = true;
                            break;
                        case NumberType.Long:
                            if (long.Parse(s) > 0)
                                bResult = true;
                            break;
                        case NumberType.Decimal:
                            if (decimal.Parse(s) > 0)
                                bResult = true;
                            break;
                        case NumberType.Double:
                            if (double.Parse(s) > 0)
                                bResult = true;
                            break;
                        case NumberType.Float:
                            if (float.Parse(s) > 0)
                                bResult = true;
                            break;
                    }
                }
            }
            return bResult;
        }

        /// <summary>
        /// Kiem tra mot chuoi co fai la chuoi ky tu
        /// </summary>
        /// <param name="s">Chuoi kiem tra.</param>
        /// <returns>Kết quả trả về	true/false.</returns>
        public static bool isAlphabetic(object s)
        {
            return CheckRegurlarExpression(s, reAlphabetic);
        }

        /// <summary>
        /// Kiem tra mot chuoi co phai chuoi ky tu va ky so.
        /// </summary>
        /// <param name="s">Chuoi kiem tra .</param>
        /// <returns>true/false.</returns>
        public static bool isAlphaNumeric(object s)
        {
            return CheckRegurlarExpression(s, reAlphanumeric);
        }

        /// <summary>
        /// Kiem tra mot chuoi co phai chuoi ky tu, ky so, " ", _.
        /// </summary>
        /// <param name="s">Chuoi kiem tra.</param>
        /// <returns>true/false.</returns>
        public static bool isChar(object s)
        {
            return CheckRegurlarExpression(s, reChar);
        }

        /// <summary>
        /// Kiem tra mot chuoi la chuoi ky tu so.
        /// </summary>
        /// <param name="s">Chuoi kiem tra.</param>
        /// <returns>true/false.</returns>
        public static bool isNumberLetter(object s)
        {
            return CheckRegurlarExpression(s, reNumberLetter);
        }

        /// <summary>
        /// kiem tra format email
        /// </summary>
        /// <param name="s">chuoi can kiem</param>
        /// <returns></returns>
        public static bool isEmail(object s)
        {
            return CheckRegurlarExpression(s, reEmail);
        }

        /// <summary>
        /// Kiem tra Username.
        /// </summary>
        /// <param name="s">Chuoi kiem tra.</param>
        /// <returns>true/false.</returns>
        public static bool isUserName(object s)
        {
            return CheckRegurlarExpression(s, reUserName);
        }

        /// <summary>
        /// Kiem tra 1 chuoi co fai la 1 URL khong?
        /// </summary>
        /// <param name="s">Chuoi kiem tra.</param>
        /// <returns>true/false.</returns>
        public static bool isURL(object s)
        {
            return CheckRegurlarExpression(s, reURL);
        }

        /// <summary>
        /// Kiem tra 1 chuoi co dung format cua filename khong?
        /// </summary>
        /// <param name="s">Chuoi kiem tra.</param>
        /// <returns>true/false.</returns>
        public static bool isFileName(object s)
        {
            return CheckRegurlarExpression(s, reFileName);
        }

        /// <summary>
        /// Ham kiem tra so IP
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool isIP(object s)
        {
            return CheckRegurlarExpression(s, reIP);
        }

        /// <summary>
        /// Kiem tra US Zip Code
        /// </summary>
        /// <param name="s">chuoi can kiem.</param>
        /// <returns>true: Zip Code OK; false: Zip Code Error</returns>
        public static bool isUSZipCode(object s)
        {
            return CheckRegurlarExpression(s, reUSZip);
        }

        /// <summary>
        /// Kiem tra US Phone
        /// </summary>
        /// <param name="s">chuoi can kiem</param>
        /// <returns>true: Phone in US; false: phone error </returns>
        public static bool isUSPhone(object s)
        {
            return CheckRegurlarExpression(s, reUSPhone);
        }

        /// <summary>
        /// kiem tra so Social Security Number o Hoa Ky
        /// </summary>
        /// <param name="s">chuoi can kiem</param>
        /// <returns></returns>
        public static bool isSSN(object s)
        {
            return CheckRegurlarExpression(s, reSSN);
        }

        #region Credit Card
        /// <summary>
        /// kiem tra so CreditCard
        /// </summary>
        /// <param name="strCardNumber">chuoi can kiem</param>
        /// <returns></returns>
        private static bool CheckCreditCard(object strCardNumber)
        {
            try
            {
                if (FunctionsUtils.IsNullOrEmpty(strCardNumber) == true)
                    return false;

                string s = strCardNumber.ToString().Trim();
                ArrayList CheckNumbers = new ArrayList();
                int CardLength = s.Length;
                int CheckSum = 0;

                // step 1
                for (int i = CardLength - 2; i >= 0; i = i - 2)
                {
                    //string aaa = s[i].ToString();
                    CheckNumbers.Add(int.Parse(s[i].ToString()) * 2);
                }

                //step 2
                for (int iCount = 0; iCount <= CheckNumbers.Count - 1; iCount++)
                {
                    int _count = 0;
                    if ((int)CheckNumbers[iCount] > 9)
                    {
                        int _numLength = ((int)CheckNumbers[iCount]).ToString().Length;
                        for (int x = 0; x < _numLength; x++)
                        {
                            _count = _count + Int32.Parse(((int)CheckNumbers[iCount]).ToString()[x].ToString());
                        }
                    }
                    else
                    {
                        _count = (int)CheckNumbers[iCount];	// single digit, just add it by itself
                    }

                    CheckSum = CheckSum + _count; // add sum to the total sum
                }

                // step 3
                int OriginalSum = 0;
                for (int y = CardLength - 1; y >= 0; y = y - 2)
                {
                    OriginalSum = OriginalSum + Int32.Parse(s[y].ToString());
                }

                return (((OriginalSum + CheckSum) % 10) == 0);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// lay Card Type tu mot so Credit Card
        /// </summary>
        /// <param name="strCardNumber">so Credit Card can lay Card Type</param>
        /// <returns>tra ve kieu Credit Card. VD: Visa, Master Card...</returns>
        public static string CreditCardTypeByName(object strCardNumber)
        {
            /*
            *CARD TYPES        *PREFIX           *WIDTH
            American Express   34, 37            15
            Diners Club        300 to 305, 36    14
            Carte Blanche      38                14
            Discover           6011              16
            EnRoute            2014, 2149        15
            JCB                3                 16
            JCB                2131, 1800        15
            Master Card        51 to 55          16
            Visa               4                 13, 16
            */
            if (FunctionsUtils.IsNullOrEmpty(strCardNumber) == true)
                return string.Empty;

            if (CheckCreditCard(strCardNumber) == false)
                return "";

            string CC = strCardNumber.ToString().Trim();
            string tmp = "";

            switch (Convert.ToInt32(CC.Substring(0, 2)))
            {
                case 34:
                case 37:
                    tmp = "American Express";
                    break;
                case 36:
                    tmp = "Diners Club";
                    break;
                case 38:
                    tmp = "Carte Blanche";
                    break;
                case 51:
                case 52:
                case 53:
                case 54:
                case 55:
                    tmp = "MasterCard";
                    break;
                default:
                    switch (Convert.ToInt32(CC.Substring(0, 4)))
                    {
                        case 2014:
                        case 2148:
                            tmp = "EnRoute";
                            break;
                        case 2131:
                        case 1800:
                            tmp = "JCB";
                            break;
                        case 6011:
                            tmp = "Discover";
                            break;
                        default:
                            //None of the above - so check the
                            //first three digits collectively
                            switch (Convert.ToInt32(CC.Substring(0, 3)))
                            {
                                case 300:
                                case 301:
                                case 302:
                                case 303:
                                case 304:
                                case 305:
                                    tmp = "Diners Club";
                                    break;
                                default:
                                    //None of the above - so simply check the first digit
                                    switch (Convert.ToInt32(CC.Substring(0, 1)))
                                    {
                                        case 3:
                                            tmp = "JCB";
                                            break;
                                        case 4:
                                            tmp = "Visa Card";
                                            break;
                                    }
                                    break;
                            }
                            break;
                    }
                    break;
            }
            return tmp;
        }

        /// <summary>
        /// dung cho Visa Card, MasterCard, Discover, American Express
        /// </summary>
        /// <param name="CreditCardNumber"></param>
        /// <returns></returns>
        public static int CreditCardTypeByNumber(object CreditCardNumber)
        {
            int iCardType = -1;
            switch (ValidateUtils.CreditCardTypeByName(CreditCardNumber))
            {
                case "Visa Card":
                    iCardType = 2;
                    break;
                case "MasterCard":
                    iCardType = 3;
                    break;
                case "Discover":
                    iCardType = 4;
                    break;
                case "American Express":
                    iCardType = 5;
                    break;
            }
            return iCardType;
        }

        /// <summary>
        /// ham dung de check Card Type cua mo65t so Credit Card co hop voi Card Type do user cung cap khong
        /// </summary>
        /// <param name="strCardNumber">so credit card can check Card Type</param>
        /// <param name="strCardType">Card Type (string)</param>
        /// <returns>kieu cua CardType duoc dinh nghia (la so nguyen)</returns>
        public static bool CheckCardType(object strCardNumber, object strCardType)
        {
            bool bResult = false;
            string s = CreditCardTypeByName(strCardNumber);
            if (s.Equals("") == false || strCardType == null)
            {
                if (s.ToLower().Equals(strCardType.ToString().ToLower()))
                    bResult = true;
            }
            return bResult;
        }

        /// <summary>
        /// check Credit Card co dung format
        /// </summary>
        /// <param name="strCardNumber">chuoi can kiem</param>
        /// <returns></returns>
        public static bool isCreditCard(object strCardNumber)
        {
            string tmp = CreditCardTypeByName(strCardNumber);
            if (tmp.Equals(""))
                return false;
            return true;
        }

        /// <summary>
        /// Check Credit Card co dung format va loai Card nhu la Visa Card, MasterCard.....
        /// </summary>
        /// <param name="CardNumber">CardNumber can check</param>
        /// <param name="sCardType">Loai Card : Visa Card, MasterCard, Discover</param>
        /// <returns></returns>
        public static bool isCreditCard(object CardNumber, string sCardType)
        {
            string tmp = CreditCardTypeByName(CardNumber);
            return tmp.Equals(sCardType);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Month"></param>
        /// <param name="Year"></param>
        /// <returns>
        /// -1 Year nho hon Current Year
        /// -2 Year = Year hien tai nhung Month nho hon Month hien tai
        /// 0 : ok
        /// </returns>
        public static int CheckExpDate(int Month, int Year)
        {
            int currYear = int.Parse(DateTime.Now.Year.ToString().Substring(2));

            if (Year < currYear)
                return -1;

            if (Year == currYear && Month < DateTime.Now.Month)
                return -2;
            return 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ExpDate"></param>
        /// <returns></returns>
        public static int CheckExpDate(string ExpDate)
        {
            int m, y;
            m = int.Parse(ExpDate.Substring(0, 2));
            y = int.Parse(ExpDate.Substring(2));
            return CheckExpDate(m, y);
        }
        #endregion
    }
}